package deploy

import (
	"errors"
	"time"

	"gddgame.cc/galaxy/utils/orm"
)

var (
	DataCenterModel = orm.NewModel("deploy_data_center", &DataCenter{
		Group: []string{},
	}, nil)
	ProjectModel            = orm.NewModel("deploy_project", &Project{}, nil)
	ProjectEnvironmentModel = orm.NewModel("deploy_environment", &Environment{}, nil)
	ProjectModuleModel      = orm.NewModel("deploy_module", &Module{}, nil)
	ProjectRecordModel      = orm.NewModel("deploy_record", &ProjectRecord{
		Nodes: []string{},
	}, nil)
	ProjectConfigModel     = orm.NewModel("deploy_config", &Config{}, nil)
	ModuleEnvironmentModel = orm.NewModel("deploy_module_environment", &ModuleEnvironment{}, nil)
)

type Process string

const (
	Wait        Process = "wait"
	InitProject         = "init"
	RunFlow             = "flow"
	Deploy              = "deploy"
	Success             = "finish"
	Fail                = "fail"
)

type ModuleType string

type FlowType string

type VarItem struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type FlowItem struct {
	Type    FlowType               `json:"type"`
	Params  map[string]interface{} `json:"params"`
	Version int                    `json:"version"`
}

type FLowItemSlice []FlowItem

func (slice FLowItemSlice) Merge(other FLowItemSlice) error {
	m := map[FlowType]*FlowItem{}
	for index := range other {
		item := other[index]
		m[item.Type] = &item
	}
	for index := range slice {
		item := &slice[index]
		if v, ok := m[item.Type]; ok {
			if item.Version != v.Version {
				return errors.New("Flow version no match")
			}
			//item.Params = append(item.Params, v.Params)
			for key, value := range v.Params {
				item.Params[key] = value
			}
		}
	}
	return nil
}

type DataCenter struct {
	Id int `json:"id" orm:"auto" sql:"INT"`
	// 集群名称
	Name string `json:"name" sql:"VARCHAR"`
	// 项目标识
	Identity string `json:"identity" sql:"VARCHAR"`
	// 对应网关地址
	Wan string `json:"wan" sql:"VARCHAR"`
	// 集群分组信息
	Group []string `json:"group" sql:"JSON"`

	Vars []VarItem `json:"vars" sql:"JSON"`
}

type Project struct {
	Id int `json:"id" orm:"auto" sql:"INT"`
	// 项目名称
	Name string `json:"name" sql:"VARCHAR"`
	// 当前状态：1可执行部署，2正在执行部署，0不可执行部署
	Status int `json:"status" sql:"INT"`

	Vars []VarItem `json:"vars" sql:"JSON"`
}

type Environment struct {
	Id           int       `json:"id" orm:"auto" sql:"INT"`
	ProjectId    int       `json:"project_id" sql:"INT"`
	DataCenterId int       `json:"data_center_id" sql:"INT"`
	Name         string    `json:"name" sql:"VARCHAR"`
	Vars         []VarItem `json:"vars" sql:"JSON"`
	Nodes        []string  `json:"nodes" sql:"JSON"`
}

type Module struct {
	Id        int `json:"id" orm:"auto" sql:"INT"`
	ProjectId int `json:"project_id" sql:"INT"`
	// 标识
	Identity string     `json:"identity" sql:"VARCHAR"`
	Type     ModuleType `json:"type" sql:"VARCHAR"`

	Vars  []VarItem     `json:"vars" sql:"JSON"`
	Flows FLowItemSlice `json:"flows" sql:"JSON"`
}

type ModuleEnvironment struct {
	Id              int        `json:"id" orm:"auto" sql:"INT"`
	EnvironmentId   int        `json:"environment_id" sql:"INT"`
	ModuleId        int        `json:"module_id" sql:"INT"`
	Vars            []VarItem  `json:"vars" sql:"JSON"`
	Number          int        `json:"number" sql:"INT"`
	Nodes           []string   `json:"nodes" sql:"JSON"`
	LastTime        *time.Time `json:"last_time" sql:"DATETIME"`
	LastSuccessTime *time.Time `json:"last_success_time" sql:"DATETIME"`

	Flows FLowItemSlice `json:"flows" sql:"JSON"`
}

type Config struct {
	Id         int        `json:"id" orm:"auto" sql:"INT"`
	ProjectId  int        `json:"project_id" sql:"INT"`
	ModuleId   int        `json:"module_id" sql:"INT"`
	Name       string     `json:"name" sql:"VARCHAR"`
	Target     string     `json:"target" sql:"VARCHAR"`
	Version    int        `json:"version" sql:"INT"`
	Content    string     `json:"content" sql:"TEXT"`
	Status     bool       `json:"status" sql:"TYINYINT"`
	CreateTime *time.Time `json:"create_time" orm:"createTime" sql:"DATETIME"`
}

type ProjectRecord struct {
	Id            int               `json:"id" orm:"auto" sql:"INT"`
	ProjectId     int               `json:"project_id" sql:"INT"`
	EnvironmentId int               `json:"environment_id" sql:"INT"`
	ModuleId      int               `json:"module_id" sql:"INT"`
	DataCenterId  int               `json:"data_center_id" sql:"INT"`
	Identity      string            `json:"identity" sql:"VARCHAR"`
	Type          ModuleType        `json:"type" sql:"VARCHAR"`
	Nodes         []string          `json:"nodes" sql:"JSON"`
	Configs       []Config          `json:"configs" sql:"JSON"`
	Vars          map[string]string `json:"vars" sql:"JSON"`
	Flows         FLowItemSlice     `json:"flows" sql:"JSON"`

	Process Process `json:"process" sql:"VARCHAR"`

	Result string `json:"result" sql:"TEXT"`

	CreateTime *time.Time `json:"create_time" orm:"createTime" sql:"DATETIME"`
	FinishTime *time.Time `json:"finish_time" sql:"DATETIME"`
}
